#include <stdlib.h>
#include "fmt.h"
#include "fmt_prt.h"

struct fmt_instance_struct* create_fmt_instance(enum fs_type_enum fs, enum dsk_type_enum dsk, ...)
{
    struct fmt_instance_struct* fmt_instance;
    struct dsk_obj_struct* dsk_obj;
    struct fs_obj_struct* fs_obj;
    va_list ap;

    fs_obj = find_fs_obj(fs);
    if(!fs_obj) {
        //
        fmt_printf("fs_obj %d not found\n", fs);
        return NULL;
    }
    dsk_obj = find_dsk_obj(dsk);
    if(!dsk_obj) {
        //
        fmt_printf("dsk_obj %d not found\n", dsk);
        return NULL;
    }
    fmt_instance = (struct fmt_instance_struct*)malloc(sizeof(struct fmt_instance_struct));
    if(!fmt_instance) {
        //
        fmt_printf("fmt_instance malloc failed\n");
        return NULL;
    }
    if(fs > FS_IMG_TYPE) {
        va_start(ap, dsk);
        fs_obj->image = va_arg(ap,const char *);
        if(!fs_obj->image) {
            fmt_printf("fs type %d need input a image path\n", fs);
            free(fmt_instance);
            return NULL;
        }
        va_end(ap);
        fmt_printf("fs image path: %s\n", fs_obj->image);
    } else {
        fs_obj->image = NULL;
    }

    fmt_instance->dsk_obj = dsk_obj;
    fmt_instance->fs_obj = fs_obj;
    if(!dsk_obj->ops->get_sector_size) {
        fmt_printf("dsk_obj %d have not function get_sector_size()\n", dsk);
        free(fmt_instance);
        return NULL;
    }
    fmt_instance->list = alloc_sector_list(dsk_obj->ops->get_sector_size());
    return fmt_instance;
}

void  flush_fmt_instance(struct fmt_instance_struct* fmt_instance)
{
    struct dsk_obj_struct* dsk_obj;
    struct fs_obj_struct* fs_obj;
    struct sector_node* node;
    uint32_t count;
    if(!fmt_instance) return;
    if(!fmt_instance->fs_obj) return;
    if(!fmt_instance->dsk_obj) return;

    dsk_obj = fmt_instance->dsk_obj;
    fs_obj = fmt_instance->fs_obj;
    if(!dsk_obj->ops->get_dsk_size) return;

    if(fs_obj->image) {
        if(!fs_obj->ops->fs_sector_init_img) {
            //
            return;
        }
        fs_obj->ops->fs_sector_init_img(fmt_instance->list, dsk_obj->ops->get_dsk_size(), fs_obj->image);
    }else {
        if(!fs_obj->ops->fs_sector_init) {
            //
            return;
        }
        fs_obj->ops->fs_sector_init(fmt_instance->list, dsk_obj->ops->get_dsk_size());
    }
    count = fmt_instance->list->nodes;

    while(count--)
    {
        node = sector_list_pop(fmt_instance->list);
        if(!node) {
            //
            fmt_printf("sector flush over - count res = %u\n", count);
            return;
        }
        dsk_obj->ops->write_sector(node->sector, node->data, node->count);
        free_sector_node(node);
    }
    fmt_printf("%s: sector_list flush over - count res = %u\n", __func__, fmt_instance->list->nodes);
}